package com.yycx.module.bus.provider.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.yycx.bpm.provider.service.ProcessInstanceService;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.common.constants.CommonConstants;
import com.yycx.common.mybatis.query.CriteriaDelete;
import com.yycx.common.mybatis.query.CriteriaUpdate;
import com.yycx.common.security.OpenHelper;
import com.yycx.common.utils.ApiAssert;
import com.yycx.common.utils.DateUtils;
import com.yycx.module.bus.client.entity.*;
import com.yycx.module.bus.client.entity.hy.HyOrder;
import com.yycx.module.bus.client.entity.hy.HyOrderDetail;
import com.yycx.module.bus.client.enums.AmountTypeEnum;
import com.yycx.module.bus.client.enums.SendTypeEnum;
import com.yycx.module.bus.provider.mapper.BusCustomBalanceMapper;
import com.yycx.module.bus.provider.service.BusCustomBalanceLogService;
import com.yycx.module.bus.provider.service.BusCustomBalanceService;
import com.yycx.common.mybatis.base.service.impl.BaseServiceImpl;
import com.yycx.common.mybatis.model.ResultBody;
import com.yycx.module.bus.provider.service.BusCustomService;
import com.yycx.module.bus.provider.service.BusPaymentService;
import com.yycx.module.file.provider.service.SysFileService;
import com.yycx.module.system.client.entity.SysBank;
import com.yycx.module.system.client.entity.SysCompany;
import com.yycx.module.system.provider.service.SysBankService;
import com.yycx.module.system.provider.service.SysCompanyService;
import org.springframework.stereotype.Service;
import com.yycx.common.base.entity.EntityMap;
import com.yycx.common.mybatis.query.CriteriaQuery;
import org.springframework.transaction.annotation.Propagation;
import com.yycx.common.mybatis.query.CriteriaSave;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;

/**
 * 客户账户收支记录接口实现类
 *
 * @author flyme
 * @date 2023-08-22
 */
@Service
@DSTransactional
public class BusCustomBalanceServiceImpl extends BaseServiceImpl<BusCustomBalanceMapper, BusCustomBalance> implements BusCustomBalanceService {

    @Resource
    private BusCustomService busCustomService;

    @Resource
    private SysBankService bankService;

    @Resource
    private BusPaymentService paymentService;

    @Resource
    private SysFileService fileService;

    @Resource
    private SysCompanyService companyService;
    @Resource
    private ProcessInstanceService processInstanceService;

    @Resource
    private BusCustomBalanceLogService busCustomBalanceLogService;

    @Override
    public ResultBody beforeAdd(CriteriaSave cs, BusCustomBalance bcb, EntityMap extra) {
        Long companyId = OpenHelper.getCompanyId();
        String customCode = bcb.getCustomCode();
        if (FlymeUtils.isNotEmpty(customCode)) {
            BusCustom custom = busCustomService.selectByCustomCode(customCode, companyId);
            SysCompany company = companyService.getById(companyId);
            if (FlymeUtils.isEmpty(custom)) {
                custom = busCustomService.syncBusCustom(company.getBusinessScope(), customCode, companyId);
            }
            bcb.setCustomId(custom.getCustomId());
        }
        bcb.setCustomBalanceId(IdWorker.getId());
        bcb.setOriginalAmount(bcb.getAmount());
        bcb.setOptType(CommonConstants.INT_1);
        bcb.setCompanyId(companyId);
        bcb.setOrganizationId(OpenHelper.getOrganizationId());
        //预收款
        bcb.setAmountType(CommonConstants.INT_2);
        bcb.setOriginalAmount(bcb.getAmount());
        bcb.setBalanceState(CommonConstants.INT_0);
        bcb.setUserId(OpenHelper.getUserId());
        bcb.setVersion(1);
        BusPayment payment = paymentService.addCustomBalancePayment(bcb);
        bcb.setRkId(payment.getPaymentId());
        return ResultBody.ok();
    }


    @Override
    public ResultBody afterEdit(CriteriaUpdate cu, BusCustomBalance customBalance, EntityMap extra) {
        paymentService.addCustomBalancePayment(customBalance);
        return super.afterEdit(cu, customBalance, extra);
    }

    @Override
    public ResultBody afterDelete(CriteriaDelete cd, Serializable[] ids) {
        Serializable id = cd.getIdValue();
        EntityMap params = cd.getRequestMap();
        String processInstanceId = params.get("processInstanceId");
        if (FlymeUtils.isNotEmpty(processInstanceId)) {
            processInstanceService.delete(processInstanceId, true, null, "删除");
        }
        return super.afterDelete(cd, ids);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<BusCustomBalance> cq, BusCustomBalance bcb, EntityMap requestMap) {
        cq.select(BusCustomBalance.class, "*");
        cq.joinSelect(BusCustom.class, "customName");
        cq.orderByDesc("bcb.createTime");
        return ResultBody.ok();
    }

    @Override
    public List<EntityMap> afterPageList(CriteriaQuery<BusCustomBalance> cq, List<EntityMap> data, ResultBody resultBody) {
        for (EntityMap datum : data) {
            Long customBalanceId = datum.getLong("customBalanceId");
            List<EntityMap> fileList = fileService.selectFileList(customBalanceId, BusCustomBalance.class);
            datum.put("fileList", fileList);
        }
        return super.afterPageList(cq, data, resultBody);
    }

    @Override
    public void afterGet(CriteriaQuery cq, EntityMap result) {
        Long customId = result.getLong("customId");
        Long customBalanceId = result.getLong("customBalanceId");
        BusCustom custom = busCustomService.getById(customId);
        if (FlymeUtils.isNotEmpty(custom)) {
            result.put("customName", custom.getCustomName());
        }
        Long bankId = result.getLong("bankId");
        SysBank bank = bankService.getById(bankId);
        if (FlymeUtils.isNotEmpty(bank)) {
            result.put("bankName", bank.getBankName());
        }
        List<EntityMap> fileList = fileService.selectFileListByFileType(customBalanceId.toString(), BusCustomBalance.class, "");
        result.put("fileList", fileList);
        super.afterGet(cq, result);
    }

    /**
     * 根据订单ID查询
     *
     * @param orderId
     * @return
     */
    @Override
    public List<BusCustomBalance> selectListByOrderId(Serializable orderId) {
        CriteriaQuery cq = new CriteriaQuery(BusCustomBalance.class);
        cq.eq(true, "orderId", orderId);
        return list(cq);
    }

    @Override
    public boolean removeByOrderId(Serializable orderId) {
        CriteriaDelete cu = new CriteriaDelete<>();
        cu.eq(true, "orderId", orderId);
        return remove(cu);
    }

    /**
     * 删除货款抵扣并更新账户余额
     *
     * @param orderId
     */
    @Override
    public void updateCustomBalance(Serializable orderId) {
        List<BusCustomBalance> busCustomBalance = selectListByOrderId(orderId);
        if (FlymeUtils.isNotEmpty(busCustomBalance)) {
            for (BusCustomBalance customBalance : busCustomBalance) {
                Long customBalanceId = customBalance.getCustomBalanceId();
                if (FlymeUtils.isNotEmpty(customBalanceId)) {
                    revokeOrderDetailsUse(customBalanceId);
                }
            }
        }
    }

    /**
     * 拆分金额
     *
     * @param customBalanceId
     * @param amount
     * @return
     */
    @Override
    public BusCustomBalance cfAmount(Long customBalanceId, BigDecimal amount) {
        return cfAmount(customBalanceId, amount, null, null);
    }

    /**
     * 拆分金额
     *
     * @param customBalanceId
     * @param amount
     * @return
     */
    @Override
    public BusCustomBalance cfAmount(Long customBalanceId, BigDecimal amount, String orderId, String orderDetailsId) {
        BusCustomBalance customBalance = getById(customBalanceId);
        if (FlymeUtils.isNotEmpty(customBalance)) {
            BigDecimal oldAmount = customBalance.getAmount();
            BigDecimal surplusAmount = oldAmount.subtract(amount);
            ApiAssert.gezero("货款余额不足", surplusAmount);
            if (FlymeUtils.gtzero(surplusAmount)) {
                customBalance.setAmount(surplusAmount);
                BusCustomBalance newObj = new BusCustomBalance();
                BeanUtil.copyProperties(customBalance, newObj);
                newObj.setAmount(amount);
                newObj.setParentId(customBalanceId);
                newObj.setOrderId(orderId);
                newObj.setOrderDetailsId(orderDetailsId);
                newObj.setCustomBalanceId(IdWorker.getId());
                save(newObj);
                updateById(customBalance);
                return newObj;
            } else {
                customBalance.setOrderId(orderId);
                customBalance.setOrderDetailsId(orderDetailsId);
                updateById(customBalance);
                return customBalance;
            }
        }
        return null;
    }

    /**
     * 撤销余额和订单的关联
     *
     * @param customBalanceId
     * @return
     */
    @Override
    public Boolean revokeOrderDetailsUse(Long customBalanceId) {
        BusCustomBalance customBalance = getById(customBalanceId);
        if (FlymeUtils.isNotEmpty(customBalance)) {
            BigDecimal oldAmount = customBalance.getAmount();
            Long parentId = customBalance.getParentId();
            if (FlymeUtils.isNotEmpty(parentId)) {
                BusCustomBalance parent = getById(parentId);
                BigDecimal parentAmount = parent.getAmount().add(oldAmount);
                parent.setAmount(parentAmount);
                updateById(parent);
                removeById(customBalanceId);
            } else {
                //父ID为空时仅需要清空关联ID
                customBalance.setOrderId(null);
                customBalance.setOrderDetailsId(null);
                updateById(customBalance);
            }
        }
        return true;
    }

    @Override
    public ResultBody revokeCfAmount(Long customBalanceId) {
        BusCustomBalance customBalance = getById(customBalanceId);
        if (FlymeUtils.isNotEmpty(customBalance)) {
            BigDecimal oldAmount = customBalance.getAmount();
            Long parentId = customBalance.getParentId();
            if (FlymeUtils.isNotEmpty(parentId)) {
                BusCustomBalance parent = getById(parentId);
                BigDecimal parentAmount = parent.getAmount().add(oldAmount);
                parent.setAmount(parentAmount);
                updateById(parent);
                removeById(customBalanceId);
            }
        }
        return ResultBody.ok("撤销成功");
    }


    @Override
    public void updateCfAmount(Long customBalanceId, BigDecimal amount) {
        BusCustomBalance customBalance = getById(customBalanceId);
        if (FlymeUtils.isNotEmpty(customBalance)) {
            BigDecimal oldAmount = customBalance.getAmount();
            BigDecimal diffAmount = oldAmount.subtract(amount);
            if (FlymeUtils.nezero(diffAmount)) {
                customBalance.setAmount(amount);
                updateById(customBalance);
                Long parentId = customBalance.getParentId();
                if (FlymeUtils.isNotEmpty(parentId)) {
                    BusCustomBalance parent = getById(parentId);
                    BigDecimal parentAmount = parent.getAmount().add(diffAmount);
                    parent.setAmount(parentAmount);
                    updateById(parent);
                }
            }
        }
    }

    @Override
    public EntityMap totalReturnAmountInfo(String selectIds) {
        CriteriaQuery<BusCustomBalance> cq = new CriteriaQuery(BusCustomBalance.class);
        cq.select("count(DISTINCT customId) customIdCount,sum(amount) amount,customId,payBankName,payCardNo");
        cq.in(true, "customBalanceId", selectIds.split(","));
        return findOne(cq);
    }

    @Override
    public Boolean updateRefundId(Long paymentId, String selectIds) {
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.set(true, "refundId", paymentId);
        cu.in(true, "customBalanceId", selectIds.split(","));
        return update(cu);
    }

    /**
     * 清空退保证金请信息
     */
    @Override
    public Boolean clearRefundId(Serializable refundId) {
        if (FlymeUtils.allNotNull(refundId)) {
            CriteriaUpdate cu = new CriteriaUpdate();
            cu.set(true, "refundId", null);
            cu.eq(true, "refundId", refundId);
            update(cu);
        }
        return true;
    }

    @Override
    public Boolean updateRefundInfo(BusPayment payment) {
        CriteriaUpdate cu = new CriteriaUpdate();
        //更新为已退款
        cu.set(true, "balanceState", CommonConstants.INT_2);
        cu.eq(true, "refundId", payment.getPaymentId());
        return update(cu);
    }


    public BusCustomBalance findByCustomCode(String customCode, Long companyId) {
        CriteriaQuery cq = new CriteriaQuery(BusCustomBalance.class);
        cq.eq(true, "customCode", customCode);
        cq.eq(true, "companyId", companyId);
        return getOne(cq);
    }

    @Override
    public BusCustomBalance findByCustomId(Long customId, Long companyId) {
        CriteriaQuery cq = new CriteriaQuery(BusCustomBalance.class);
        cq.eq(true, "customId", customId);
        cq.eq(true, "companyId", companyId);
        return getOne(cq);
    }


    @Override
    public void saveHkCustomBalance(String customCode, Long companyId, String orderId, BigDecimal amount) {
        BusCustomBalance busCustomBalance = findByCustomCode(customCode, companyId);
        BusCustom custom = busCustomService.selectByCustomCode(customCode, companyId);
        if (FlymeUtils.isEmpty(busCustomBalance)) {
            busCustomBalance = new BusCustomBalance();
            busCustomBalance.setAmount(amount);
            busCustomBalance.setCustomId(custom.getCustomId());
            busCustomBalance.setAmountType(CommonConstants.INT_1);
            busCustomBalance.setOptType(CommonConstants.INT_1);
            busCustomBalance.setVersion(1);
            busCustomBalance.setUserId(OpenHelper.getUserId());
            save(busCustomBalance);
        } else {
            BigDecimal oldAmount = FlymeUtils.getBigDecimal(busCustomBalance.getAmount(), "0");
            //计算新的货款余额
            BigDecimal newAmount = oldAmount.add(amount);
            //设置新的货款余额
            busCustomBalance.setAmount(newAmount);
            //更新余额
            updateById(busCustomBalance);
        }
        //保存收支记录
        BusCustomBalanceLog customBalanceLog = new BusCustomBalanceLog();
        customBalanceLog.setCustomCode(customCode);
        customBalanceLog.setCustomId(custom.getCustomId());
        customBalanceLog.setAmount(amount);
        customBalanceLog.setAmountDate(DateUtils.getNowDate());
        customBalanceLog.setOrderId(orderId);
        customBalanceLog.setCompanyId(companyId);
        customBalanceLog.setUserId(busCustomBalance.getUserId());
        customBalanceLog.setAmountType(CommonConstants.INT_1);
        if (FlymeUtils.isNotEmpty(amount) && FlymeUtils.gtzero(amount)) {
            //收入
            customBalanceLog.setOptType(CommonConstants.INT_1);
        }
        if (FlymeUtils.isNotEmpty(amount) && FlymeUtils.ltzero(amount)) {
            //支出
            customBalanceLog.setOptType(CommonConstants.INT_2);
        }
        busCustomBalanceLogService.save(customBalanceLog);
    }

    @Override
    public void saveHkCustomBalance(Long customId, BigDecimal amount) {
        BusCustom custom = busCustomService.getById(customId);
        Long companyId = custom.getCompanyId();
        BusCustomBalance busCustomBalance = findByCustomId(customId, companyId);
        if (FlymeUtils.isEmpty(busCustomBalance)) {
            busCustomBalance = new BusCustomBalance();
            busCustomBalance.setAmount(amount);
            busCustomBalance.setCustomId(custom.getCustomId());
            busCustomBalance.setCustomCode(custom.getCustomCode());
            busCustomBalance.setCompanyId(companyId);
            busCustomBalance.setAmountType(CommonConstants.INT_1);
            busCustomBalance.setOptType(CommonConstants.INT_1);
            busCustomBalance.setVersion(1);
            busCustomBalance.setUserId(OpenHelper.getUserId());
            save(busCustomBalance);
        } else {
            //设置新的货款余额
            busCustomBalance.setAmount(amount);
            //更新余额
            updateById(busCustomBalance);
        }

    }
}
